package com.aratek.salary.service;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Yvan Jiang
 * @version 0.0.1
 * @Title Worker
 * @note 异步进行处理，防止断线
 * @note Copyright 2016 by Aratek . All rights reserved
 * @time 2017/11/16
 **/
@Component
public class Worker {
    private static final Logger LOG = LoggerFactory.getLogger(Worker.class);
    //工作线程
    private static final ExecutorService WORKER_THREAD =
            Executors.newSingleThreadExecutor((runnable) -> new Thread(runnable,"WORKER"));
    private final AtomicInteger total = new AtomicInteger(0);
    private final AtomicInteger success = new AtomicInteger(0);
    private static final List<String> ERROR_LIST = new ArrayList<>();
    private SalaryReportSplitter splitter;
    private String templateFilePath;
    @Autowired
    private MailService mailService;

    @PostConstruct
    public void init() throws IOException {
        Resource resource = new ClassPathResource("template.xlsx");
        File templateFile = File.createTempFile("salary","template");
        FileUtils.copyToFile(resource.getInputStream(),templateFile);
        templateFilePath = templateFile.getAbsolutePath();
        templateFile.deleteOnExit();
        WORKER_THREAD.submit(new MailWorkerThread());
    }

    public void startWork(File dataFile) throws IOException {
        ERROR_LIST.clear();
        success.set(0);
        splitter = SalaryReportSplitter.instance(dataFile,this.templateFilePath);
        LOG.info("Start file work!!");
        int size = splitter.dispatch();
        LOG.info("Total file count {},start listener",size);
        total.set(size);

    }

    private class MailWorkerThread implements Runnable{
        private MailWorkerThread(){

        }
        @Override
        public void run() {
            while (true){
                try {
                    Map<String,File> map = SalaryReportSplitter.getExcelFileList().take();
                    for(Map.Entry<String,File> entry : map.entrySet()){
                        String email = entry.getKey();
                        try {
                            Thread.sleep(100);
                            mailService.sendEmail(email, entry.getValue());
                            success.incrementAndGet();
                        }catch (Throwable throwable){
                            LOG.error("send error {}",entry.getKey());
                            LOG.error(entry.getKey(),throwable);
                            ERROR_LIST.add(email + ' ' +throwable.getMessage());
                        }finally {
                            if(!FileUtils.deleteQuietly(entry.getValue())){
                                LOG.warn("Cannot delete file {}",entry.getValue());
                            }
                        }
                    }
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
    }

    public void cleanFile(){
        if(!SalaryReportSplitter.isWorking() && splitter!=null) {
            splitter.deleteSrcFile();
        }
    }

    public AtomicInteger getTotal() {
        return total;
    }

    public AtomicInteger getSuccess() {
        return success;
    }

    public static List<String> getErrorList() {
        return ERROR_LIST;
    }

    @PreDestroy
    public void preDestroy(){
        WORKER_THREAD.shutdownNow();
        SalaryReportSplitter.destroy();
    }
}
